﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NetMQ;
using NetMQ.Sockets;

namespace NetMQ_Router_Client
{
    class Program
    {
        // NOTES
        // 1. Use ThreadLocal<DealerSocket> where each thread has
        //    its own client DealerSocket to talk to server
        // 2. Each thread can send using it own socket
        // 3. Each thread socket is added to poller
        static void Main(string[] args)
        {

            const int delay = 5000; // millis

            var clientSocketPerThread = new ThreadLocal<DealerSocket>();
            using (var poller = new NetMQPoller())
            {
                // Start some threads, each with its own DealerSocket
                // to talk to the server socket. Creates lots of sockets,
                // but no nasty race conditions no shared state, each
                // thread has its own socket, happy days.
                for (int i = 0; i < 2; i++)
                {
                    Task.Factory.StartNew(state =>
                    {
                        DealerSocket client = null;

                        if (!clientSocketPerThread.IsValueCreated)
                        //建立客户端列表
                        {
                            client = new DealerSocket();
                            client.Options.Identity =
                                Encoding.Unicode.GetBytes(state.ToString());
                            Console.WriteLine(client.Options.Identity);  //输出客户端标记
                            client.Connect("tcp://127.0.0.1:5556");
                            client.ReceiveReady += Client_ReceiveReady;
                            clientSocketPerThread.Value = client;
                            poller.Add(client);
                        }
                        else
                        {
                            client = clientSocketPerThread.Value;
                        }

                        while (true)
                        {
                            for (int n = 0; n < 1; n++)
                            {
                                var messageToServer = new NetMQMessage();
                                //messageToServer.AppendEmptyFrame();
                                //messageToServer.Append(i.ToString());
                                messageToServer.Append($"this is message {n} to server state is {state}");
                                PrintFrames("Client Sending", messageToServer);
                                client.SendMultipartMessage(messageToServer);
                                Thread.Sleep(delay);
                            }
                            
                        }

                    }, string.Format("client {0}", i), TaskCreationOptions.LongRunning);
                }

                // start the poller
                poller.RunAsync();
                Console.ReadKey();
            }
        }
        static void Client_ReceiveReady(object sender, NetMQSocketEventArgs e)
        {
            
            string result = e.Socket.ReceiveFrameString();
            Console.WriteLine($"REPLY {result}");

        }

        static void PrintFrames(string operationType, NetMQMessage message)
        {
            for (int i = 0; i < message.FrameCount; i++)
            {
                Console.WriteLine("{0} Socket : Frame[{1}] = {2}", operationType, i,
                    message[i].ConvertToString());
            }
        }
    }
}
